package net.sf.fc.script;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBException;

import net.sf.fc.script.gen.copy.CopyScript;
import net.sf.fc.script.gen.copy.Dst;
import net.sf.fc.script.gen.copy.Map;
import net.sf.fc.script.gen.copy.Paths;
import net.sf.fc.script.gen.copy.Src;
import net.sf.fc.script.gen.copy.Type;
import net.sf.fc.script.gen.options.OptionsScript;

public class CopyScriptProxy {

    private final CopyScript copyScript;
    private final CopyScript defaultCopyScript;
    private final ScriptHelper<CopyScript> copyScriptHelper;
    private final File copyScriptXml;

    public CopyScriptProxy(ScriptHelper<CopyScript> copyScriptHelper, OptionsScript defaultOptions) {
        this.copyScriptHelper = copyScriptHelper;
        copyScript = createEmptyCopyScriptObject(defaultOptions);
        defaultCopyScript = createDefaultCopyScriptObject(defaultOptions);
        copyScriptXml = null;
    }

    public CopyScriptProxy(ScriptHelper<CopyScript> copyScriptHelper, OptionsScript defaultOptions,
            File copyScriptXml) throws JAXBException {
        this.copyScriptHelper = copyScriptHelper;
        this.copyScriptXml = copyScriptXml;
        defaultCopyScript = createDefaultCopyScriptObject(defaultOptions);
        copyScript = copyScriptXml.exists() ? copyScriptHelper.unmarshal(copyScriptXml) : createEmptyCopyScriptObject(defaultOptions);
        copyScriptXml = null;
    }

    private CopyScript createDefaultCopyScriptObject(OptionsScript defaultOptions) {
        CopyScript cs = new CopyScript();
        cs.setDefaultOptions(defaultOptions);
        cs.getMapList().add(createDefaultMap());
        return cs;
    }

    private Map createDefaultMap() {
        Map map = new Map();
        map.setSrc(createDefaultSrc());
        map.getDstList().add(createDefaultDst());
        return map;
    }

    private Src createDefaultSrc() {
        Src src = new Src();
        src.getPaths().add(createDefaultPaths());
        return src;
    }

    private Paths createDefaultPaths() {
        Paths paths = new Paths();
        paths.getPathList().add(new File(System.getProperty("user.dir")));
        return paths;
    }

    private Dst createDefaultDst() {
        Dst dst = new Dst();
        dst.setType(Type.DIRECTORY);
        dst.getPaths().add(createDefaultPaths());
        return dst;
    }

    private CopyScript createEmptyCopyScriptObject(OptionsScript defaultOptions) {
        CopyScript copyScript = new CopyScript();
        copyScript.setDefaultOptions((OptionsScript)defaultOptions.copyTo(null));
        return copyScript;
    }

    // CopyScript getter methods
    public OptionsScript getDefaultOptions() {
        return (OptionsScript)copyScript.getDefaultOptions().copyTo(null);
    }

    public int getMapListSize() {
        return copyScript.getMapList().size();
    }

    public Map getMapAt(int index) {
        return (Map)copyScript.getMapList().get(index).copyTo(null);
    }

    public List<Map> getMapList() {
        List<Map> mapLstCpy = new ArrayList<Map>(copyScript.getMapList().size());
        for(Map so: copyScript.getMapList()) {
            mapLstCpy.add((Map)so.copyTo(null));
        }
        return mapLstCpy;
    }

    public CopyScript getDefaultCopyScript() {
        return (CopyScript)defaultCopyScript.copyTo(null);
    }

    // This is to get the default options that were passed in when the CopyScriptProxy object was first created. This
    // method should be used if we fail to get the default options from disk.
    public OptionsScript getCachedDefaultOptions() {
        return (OptionsScript)defaultCopyScript.getDefaultOptions().copyTo(null);
    }

    // CopyScript setter methods
    public void setDefaultOptions(OptionsScript defaultOptions) {
        if(defaultOptions == null) throw new NullPointerException("Default Options must not be null");
        copyScript.setDefaultOptions((OptionsScript)defaultOptions.copyTo(null));
    }

    public void addMap(Map copyMap) {
        if(copyMap == null) throw new NullPointerException("Map must not be null");
        copyScript.getMapList().add((Map)copyMap.copyTo(null));
    }

}
